/**
 * Copyright (C) 2013 Christos Koufogiannakis
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.easychart.chart;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.util.AttributeSet;

public class BarChart extends ChartBaseClass {	
	private float barWidth;
	private float totalBarWidth;
	private float barPaddingOnEachSide;	
	
	private List<Double> barValues = new ArrayList<Double>();
	
	/** 
	 * Constructor for BarChart
	 * 
	 * @param context
	 * @param attrs
	 */
	public BarChart(Context context, AttributeSet attrs) {			
		super(context, attrs);	
		initializeBarChart();
	}
	
	/**
	 * Constructor for BarChart
	 * 
	 * @param context
	 */
	public BarChart(Context context) {			
		super(context);	
		initializeBarChart();
	}

	/**
	 * Initializes bar chart specific parameters
	 */
	private void initializeBarChart(){
		parameters.SHOW_VERTICAL_GRID.setValue(false);
	}

	/**
	 * Set the list of values for the bars and the list of corresponding labels
	 *  
	 * @param values is the list of values to be plotted
	 * @param labels is the list of labels corresponding to the values. 
	 * The size of barLabels must be same as the size of values.
	 * 
	 * @throws IllegalArgumentException if values is null or
	 * the two lists have different sizes
	 */
	public void setValuesAndLabels(List<Double> values, List<String> labels)
			throws IllegalArgumentException {
		checkNullity(values);
		this.barValues = values;

		if (labels == null || values.size() != labels.size()){
			throw new IllegalArgumentException("The two list cannot be of different sizes");
		}
		else{
			super.setXLabels(labels);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		//set minY and maxY before calling the base class method
		if (!barValues.isEmpty()) {
			minY = Collections.min(barValues);
			maxY = Collections.max(barValues);
		}
		
		super.onDraw(canvas);
				
		// do these calculations before calling drawXLabels and drawBars
		totalBarWidth = plotWidth/xLabels.size();
		barPaddingOnEachSide = parameters.BAR_PAD_EACH_SIDE_PERCENT_OF_BARWIDTH.getValue() 
				* totalBarWidth/100;
		barWidth = totalBarWidth - 2 * barPaddingOnEachSide;
	
		super.drawXLabels(canvas, totalBarWidth, (int) (totalBarWidth/2));
		
		// draw bars now.
		drawBars(canvas);
	}
	
	/**
	 * Draws the bars
	 * 
	 * @param canvas
	 */
	private void drawBars(Canvas canvas){		
		mPaint.setTextAlign(Align.CENTER);
		mPaint.setTextSize(vertexLabelTextSize);
		mPaint.setStyle(Style.FILL);
		
		for (int i=0; i < Math.min(barValues.size(), xLabels.size()); i++){
			mPaint.setColor(parameters.BAR_COLOR.getValue());
			
			//calculate bar's corner points
			float barHeight = (float) (maxPointHeight * Math.abs(barValues.get(i))/(yLabelRange));
			float barXLeft = i*totalBarWidth + barPaddingOnEachSide + plotLeftX;
			float barXRight = barXLeft + barWidth;		
			float barYTop;
			float barYBottom;	
			if (barValues.get(i) >= 0){
				barYTop = (float) (plotBottomYInside - maxPointHeight * (barValues.get(i) - minYLabel)/(yLabelRange));
				barYBottom =  barYTop + barHeight;
			}
			else{
				barYBottom = (float) (plotBottomYInside - maxPointHeight * (barValues.get(i) - minYLabel)/(yLabelRange));
				barYTop =  barYBottom - barHeight;
			}
			
			//draw a rectangle surrounding the bar. 
			canvas.drawRect(barXLeft, barYTop, barXRight, barYBottom, mPaint);	
			
			// draw the bar labels
			if (parameters.SHOW_VERTEX_LABELS.getValue()){
				continue;
			}
			
			mPaint.setColor(parameters.VERTEX_LABELS_TEXT_COLOR.getValue());
			String label_str =  labelValueToString(barValues.get(i), true);
			mPaint.setTextSize(adjustTextSize(label_str, vertexLabelTextSize, totalBarWidth));
								
			float labelX = plotLeftX + totalBarWidth * i + totalBarWidth/2;
			float labelY;
			
			if (barValues.get(i) >=0){	
				labelY = barYTop - parameters.VERTEX_TO_VERTEX_LABEL.getValue();	
				if (labelY - bounds.height() < plotTopY)
					labelY = barYTop + parameters.VERTEX_TO_VERTEX_LABEL.getValue() + bounds.height();	
			}
			else{
				labelY = barYBottom + parameters.VERTEX_TO_VERTEX_LABEL.getValue()  +  bounds.height() ;	
				if (labelY > plotBottomY)
					labelY = barYBottom - parameters.VERTEX_TO_VERTEX_LABEL.getValue();	
			}
			
			canvas.drawText(label_str, labelX , labelY, mPaint);
		}
		
		// draw the x-axis
		super.drawsXAxis(canvas);
	}
}
